using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;

namespace cs2335.CCT
{
    public class TextBox : IComponent, ITextBox
    {
        protected Rectangle TextRectangle = new Rectangle(0,0,130,17);
        protected bool canWrite;
        protected StringFormat labelFormat = new StringFormat(StringFormatFlags.NoClip);
        protected SolidBrush TextBrush = new SolidBrush(Color.White);
        protected Font font = new Font("SansSerif", 10);
        protected CCTForm owner;
        protected string text = "";
        protected bool hasFocus = false;
        protected bool hidden = false;
        protected string name;
        protected int cursorIndex;
        protected int maxLength;
        protected Region[] bounds;
        protected RectangleF[] tchar;
        protected CharacterRange[] characterRanges;

        #region Properties
        public Point Location
        {
            get { return TextRectangle.Location; }
            set { TextRectangle.Location = value; Invalidate(); }
        }

        public Rectangle Bounds
        {
            get { return TextRectangle; }
            set { TextRectangle = value; Invalidate(); }
        }

        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        public System.Drawing.Font Font
        {
            get { return font; }
            set { font = value; Invalidate(); }
        }

        public string Text
        {
            get { return text; }
            set { text = value; Invalidate(); }
        }

        public CCTForm Owner
        {
            get { return owner; }
            set { owner = value; }
        }

        public Color BackColor
        {
            get { return TextBrush.Color; }
            set { TextBrush.Color = value; Invalidate(); }
        }
        #endregion

        #region Events
        public event EventHandler Click;
        public event EventHandler GotFocus;
        public event EventHandler KeyPress;
        public event EventHandler LostFocus;
        public event EventHandler Paint;
        public event EventHandler KeyDown;
        #endregion

        public TextBox() 
        {
            cursorIndex = 0;
            maxLength = 15;
            bounds = new Region[maxLength+1];
            tchar = new RectangleF[maxLength+1];
            tchar[0] = (RectangleF)TextRectangle;

        }

        /// <summary>
        /// Notifies its CCTForm that it needs a redraw
        /// </summary>
        public void Invalidate()
        {
            if (owner != null)
            {
                owner.Invalidate();
            }
        }


        /// <summary>
        /// Conceals the component from the user.
        /// </summary>
        public void Hide()
        {
            hidden = true;
            Invalidate();
        }


        /// <summary>
        /// Displays the component to the user.
        /// </summary>
        public void Show()
        {
            hidden = false;
            Invalidate();
        }

        /// <summary>
        /// Raises the Paint event
        /// </summary>
        /// <param name="e">A PaintEventArgs that contains the event data</param>
        public void OnPaint(PaintEventArgs e)
        {
            if (!hidden)
            {
                Graphics g = e.Graphics;
                g.FillRectangle(TextBrush, TextRectangle);
                g.DrawRectangle(Pens.Black, TextRectangle);
                g.DrawString(text, font, Brushes.Black, (RectangleF)TextRectangle, labelFormat);
                
                int numChars = text.Length;
                if (numChars != 0)
                {
                    characterRanges = new CharacterRange[numChars];
                    for (int i = 0; i < numChars; i++)
                    {
                        characterRanges[i] = new CharacterRange(i, 1);
                    }

                    labelFormat.SetMeasurableCharacterRanges(characterRanges);

                    bounds = g.MeasureCharacterRanges(text, font, (RectangleF)TextRectangle, labelFormat);
                    for (int i = 0; i < bounds.Length; i++)
                    {
                        tchar[i] = bounds[i].GetBounds(g);
                    }   
                }
                

                if (Paint != null)
                {
                    Paint(this, e);
                }
            }
        }


        /// <summary>
        /// Raises the GotFocus event
        /// </summary>
        /// <param name="e">An EventArgs that contains the event data</param>
        public void OnGotFocus(EventArgs e)
        {
            if (!hasFocus)
            {
                canWrite = true;
                hasFocus = true;
                text = text.Insert(cursorIndex, "|");
                Invalidate();
            }
            if (GotFocus != null)
            {
                GotFocus(this, e);
            }
        }


        /// <summary>
        /// Raises the LostFocus event
        /// </summary>
        /// <param name="e">An EventArgs that contains the event data</param>
        public void OnLostFocus(EventArgs e)
        {
            if (hasFocus)
            {
                canWrite = false;
                hasFocus = false;
                text = text.Remove(cursorIndex, 1);
                cursorIndex = text.Length;
                Invalidate();
            }

            if (LostFocus != null)
            {
                LostFocus(this, e);
            }
        }


        /// <summary>
        /// Called when the mouse is clicked on the component
        /// </summary>
        /// <param name="e">A MouseEventArgs that contains the event data</param>
        public void OnMouseClick(System.Windows.Forms.MouseEventArgs e)
        {
            if (TextRectangle.Contains(e.X, e.Y))
            {
                
                canWrite = true;
                
                 for (int i = 0; i < text.Length && text.Length>0; i++)
                 {

                     if (tchar[i].Contains(e.X, e.Y))
                     {
                         if (hasFocus)
                            text = text.Remove(cursorIndex,1);
                         
                         cursorIndex = i;
                         text = text.Insert(cursorIndex, "|");
                         hasFocus = true;
                         Invalidate();
                     }                
                 }
            }
            if (!TextRectangle.Contains(e.X, e.Y))
            {
                canWrite = false;
            }
            if (Click != null)
            {
                Click(this, e);
            }
        }



        /// <summary>
        /// Called when a key is pressed when the component has focus
        /// </summary>
        /// <param name="e">A KeyPressEventArgs that contains the event data</param>
        public void OnKeyPress(System.Windows.Forms.KeyPressEventArgs e)
        {
            string enter;
            if(canWrite)
            {

                if (e.KeyChar != (char)Keys.Back && e.KeyChar != (char)Keys.Return && text.Length<=maxLength
                    && e.KeyChar != (char)Keys.Tab)
                {
                  
                        enter = e.KeyChar.ToString();
                        text = text.Insert(cursorIndex, enter);
                        cursorIndex++;
                        Invalidate();
                                     
                }
                if (KeyPress != null)
                {
                    KeyPress(this, e);
                }
            }
        }

        public void OnKeyDown(KeyEventArgs e)
        {
            if(canWrite)
            {
                if(e.KeyData == Keys.Back)
                {
                    if (cursorIndex > 0)
                    {
                        text = text.Remove(cursorIndex - 1, 1);
                        cursorIndex--;
                        Invalidate();
                    }
                }
                if (e.KeyData == Keys.Right)
                {
                    if (cursorIndex < text.Length - 1)
                    {
                        
                        //text = text.Replace("|", text[cursorIndex + 1].ToString());
                        //cursorIndex++;
                        
                        text = text.Remove(cursorIndex, 1);
                        cursorIndex++;
                        text = text.Insert(cursorIndex, "|");
                        Invalidate();
                    }
                }
                if (e.KeyData == Keys.Left)
                {
                    if (cursorIndex > 0)
                    {
                        //text = text.Replace("|", text[cursorIndex - 1].ToString());
                        //cursorIndex--;
                        
                        text = text.Remove(cursorIndex,1);
                        cursorIndex--;
                        text = text.Insert(cursorIndex, "|");
                        Invalidate();
                    }
                }
                if (KeyDown != null)
                {
                    KeyDown(this, e);
                }

            }
        }

        #region ITextBox Members

        public int MaxLength
        {
            get
            {
                return maxLength;
            }
            set
            {
                maxLength = value;
            }
        }

        #endregion
    }
}
